package demo03

import "fmt"

/*
总结
Golang 由于语言本身的特性，不支持函数重载，函数式选项 的编程模式在一定程度上解决了其他语言需要通过函数重载解决的问题。函数式选项 编程有以下优点：
	任意顺序传递参数
	支持默认值
	向后兼容性
	很容易维护和扩展
虽然 函数式选项 编程模式有很多优点，但是设计模式的存在都是为了弥补语言特性的缺陷的一种手段。
它是为了解决代码扩展性的问题，往往是通过增加抽象牺牲了简单性，切勿过度使用。有些简单的配置，就不需要设计的这么通用了。

函数式选项模式的使用场景有哪些呢：
我们一般用来配置一些基础的服务配置，比如MySQL，Redis，Kafka的配置，很多可选参数，可以方便动态灵活的配置想要配置的参数。
*/

// ----- 第三方包提供的配置 ------
type server05 struct {
	addr string // 必选
	port int

	timeout int // 可选
	maxConn int
}

// 第三方包需要提供一个初始化的方法，屏蔽内部包的配置细节。
// 采用 function optional 模式
type option5 func(s *server05)

func SetTimeout(timeout int) option5 {
	return func(s *server05) {
		s.timeout = timeout
	}
}

func SetMaxConn(max int) option5 {
	return func(s *server05) {
		s.maxConn = max
	}
}

func NewServer05(addr string, port int, option5s ...option5) *server05 {
	s := &server05{
		addr: addr,
		port: port,
	}
	for _, op := range option5s {
		op(s)
	}
	return s
}

// Start 使用
func (s *server05) Start() {
	fmt.Printf("server05 start,config:%v", s)
}

// OptionFunDemo2 ----- 外部包调用 ------
func OptionFunDemo2() {
	s := NewServer05("127.0.0.1", 8080, SetTimeout(10), SetMaxConn(100))
	s.Start()
}
